/*
 * \brief  Core-specific child
 * \author Norman Feske
 * \date   2006-07-24
 */

/*
 * Copyright (C) 2006-2009 Norman Feske
 * Genode Labs, Feske & Helmuth Systementwicklung GbR
 *
 * This file is part of the Genode OS framework, which is distributed
 * under the terms of the GNU General Public License version 2.
 */

#ifndef _CORE__INCLUDE__CORE_CHILD_H_
#define _CORE__INCLUDE__CORE_CHILD_H_

#include <base/child.h>

namespace Genode {

	class Core_child : public Child
	{
		private:

			Local_service_pool *_local_services;

		public:

			/**
			 * Constructor
			 */
			Core_child(const char             *name,
			           Dataspace_capability    elf_ds,
			           Ram_session_capability  ram_session,
			           Cpu_session_capability  cpu_session,
			           Cap_session            *cap_session,
			           Local_service_pool     *local_services)
			:
				Child(name, elf_ds, ram_session, cpu_session, cap_session, 0),
				_local_services(local_services)
			{ }


			/**********************
			 ** Parent interface **
			 **********************/

			Session_capability session(const char *service_name, const char *args)
			{
				/* try if request refers to an initial session */
				try {
					return Child::session(service_name, args);
				} catch (...) { }

				size_t ram_quota = Arg_string::find_arg(args, "ram_quota").ulong_value(0);

				/* look up our locally implemented services */
				Local_service *ls = _local_services->find(service_name);
				if (!ls)
					throw Service_denied();

				if (_ram_session_client.transfer_quota(env()->ram_session_cap(), ram_quota)) {
					PERR("Child has not enough quota to make a donation of %zd", ram_quota);
					throw Quota_exceeded();
				}

				Session_capability session;
				try {
					session = ls->root()->session(args);
				} catch (Root::Quota_exceeded) {
					throw Quota_exceeded();
				} catch (Root::Invalid_args) {
					throw Service_denied();
				}

				try {
					_add_session(Session(session, ls->root(), ram_quota, 0, service_name));
				} catch (Ram_session::Quota_exceeded) {
					throw Quota_exceeded();
				}

				return session;
			}
	};
}

#endif /* _CORE__INCLUDE__CORE_CHILD_H_ */
